<template>
	<view class="content" @touchstart="touchstart" @touchmove="touchmove" @touchend="touchend">
		<canvas :style="{ width: cw + 'px', height: ch + 'px'}" canvas-id="myCanvas" id="myCanvas"> </canvas>
	</view>
</template>

<script>
	import utils from './utils.js';
	document?.body.addEventListener('touchmove', function(e) {
		e.preventDefault();
	}, {
		passive: false
	});
	export default {
		data() {
			return {
				ctx: null,
				ctxConfig: {
					speed: 11.5, // rect下落速度(秒)
					setTime: 16, // 刷新率
					step: 10, // rect列表更新步长
					step2: 0, // rect下落步长,
					deviationY: 0, // 设置rect竖直触碰偏差(px)
				},
				resContainer: null, // Promise resovle容器
				intervalContainer: null, // 延时器Id容器
				isStart: false,
				isDisable: false,
				cw: 0,
				ch: 0,
				sw: 0,
				sh: 0,
				rect: [],
				rectView: [],
				long: 100000, // rect个数
				iterators: 0, // 当前数组迭代次数
				touchArr: [], // 触碰数组
			}
		},
		onLoad() {
			let sysInfo = uni.getSystemInfoSync();
			this.cw = sysInfo.screenWidth;
			this.ch = sysInfo.screenHeight;
			this.sw = this.cw / 4;
			this.sh = this.ch / 4;
			this.ctxConfig.deviationY = this.sh * 3 / 4;
		},
		onReady() {
			this.initData();
			this.initCtx();
		},
		methods: {
			render(context, step) {
				let sw = this.sw;
				let sh = this.sh;
				// context.setStrokeStyle('#000');
				// context.setLineWidth(1);
				this.rectView.map(e => {
					context.setFillStyle(e.color);
					context.fillRect(sw * e.xNum, sh * e.yNum + step, sw, sh);
				});
				// context.stroke();
				context.draw();
			},
			renderRectList() {
				let nums = [0, 1, 2, 3];
				let tempNums = [0, 2, 3];
				let tempArr = [];
				let {
					ctxConfig: {
						step
					},
					iterators
				} = this;

				for (let i = 0; i < step; i++) {
					let ind = utils.randomNum(2);
					let xNum = tempNums[ind];
					let yNum = 3 - step * iterators + 1 + i;
					let inds = this.long - step * iterators + i;
					tempNums = JSON.parse(JSON.stringify(nums));
					let index = tempNums.indexOf(xNum);
					tempNums.splice(index, 1);
					tempArr.push({
						xNum,
						yNum,
						ind: inds,
						color: inds > this.long - 3 ? "#ff0" : '#000'
					});
				};

				// 防止相邻Rect出现重叠
				if (tempArr[tempArr.length - 1].xNum === this.rect[0]?.xNum) {
					tempNums = JSON.parse(JSON.stringify(nums));
					let prevInd = tempArr[tempArr.length - 1].xNum;
					let nextInd = tempArr[tempArr.length - 2].xNum;
					tempNums = tempNums.filter(e => ![prevInd, nextInd].includes(e));
					let ind = utils.randomNum(1);
					tempArr[tempArr.length - 1].xNum = tempNums[ind];
				};

				this.rect.unshift(...tempArr);
				if (this.rect.length > 20) {
					this.rect = this.rect.slice(0, 20);
				};
			},
			initCtx() {
				this.ctx = uni.createCanvasContext("myCanvas");
				this.render(this.ctx, 0);
			},
			initData() {
				this.tempNum = this.long;
				this.iterator();
				this.rect.map((e, ind, arr) => {
					if (ind >= arr.length - 8) {
						this.rectView.push({
							...e,
						});
					};
				});
			},
			iterator() {
				this.iterators++;
				this.renderRectList();
			},
			overGame() {
				this.isStart = false;
				this.isDisable = true;
				clearInterval(this.intervalContainer);
				this.render(this.ctx, this.ctxConfig.step2);
			},
			startGame() {
				let oldStep = 0;
				this.isStart = true;
				let {
					speed,
					setTime
				} = this.ctxConfig;
				this.intervalContainer = setInterval(() => {
					this.ctxConfig.step2 += (speed * (this.sh) * setTime / 1000); // speed转step
					let el = this.rectView[this.rectView.length - 1];
					if (el) {
						let yNum = el.yNum;
						if ((this.sh * yNum + this.ctxConfig.step2) >= (this.ch)) {
							if (el.color == '#000') {
								this.ctxConfig.step2 = oldStep;
								return this.overGame();
							};
							oldStep = this.ctxConfig.step2;
							this.rectView.splice(this.rectView.length - 1, 1);
							if (this.rectView[0].ind === this.rect[0].ind + 1) {
								if (this.rectView[0].ind <= 0) return;
								this.iterator();
							};
							let index = this.rect.findIndex((e) => e.ind === this.rectView[0].ind - 1);
							if (index <= 0 || this.rectView[0].ind <= 0) return;
							this.rectView.unshift({
								...this.rect[index]
							});
						};
						this.render(this.ctx, this.ctxConfig.step2);
					}
				}, setTime);
			},
			isTouchTrue(e, el) {
				e = e.changedTouches.at(-1);
				let {
					sw,
					sh,
					ctxConfig: {
						step2,
						deviationY
					}
				} = this;
				let clientX = parseInt(e.clientX);
				let clientY = parseInt(e.clientY);
				let xMin = parseInt(sw * el.xNum);
				let yMin = parseInt(sh * el.yNum + step2);
				let xMax = parseInt(xMin + sw);
				let yMax = parseInt(yMin + sh);
				deviationY = parseInt(deviationY);
				let inX = (clientX > xMin) && (clientX < xMax);
				let inY = (clientY + deviationY > yMin) && (clientY - deviationY < yMax);
				return inX && inY;
			},
			touchstart(e) {
				if (this.isDisable) return;
				let {
					clientX,
					clientY,
				} = e.changedTouches[0];
				let el = null;
				let ii = -1;
				for (let i = this.rectView.length - 1; i >= 0; i--) {
					if (this.rectView[i].color == '#000') {
						el = this.rectView[i];
						break;
					};
				};
				if (this.isTouchTrue(e, el)) {
					el.color = "#ff0";
					if (!this.isStart) {
						this.startGame();
					} else {};
				};
			},
			touchmove(e) {},
			touchend() {

			},
		}
	}
</script>

<style lang="scss" scoped>
	#myCanvas01 {
		border: 1px solid #000;
		box-sizing: border-box;
	}

	.content {
		width: 100vw;
		height: 100vh;
		display: flex;
		justify-content: center;
		// align-items: center;
		overflow: hidden;
	}

	.list {
		width: 300rpx;
		height: 600rpx;
		color: red;
		position: relative;

		.item {
			width: 100%;
			height: 100%;
			box-sizing: border-box;
			border: 1px solid #000;
			position: absolute;
			display: flex;
			justify-content: center;
			align-items: center;
		}
	}
</style>
